`include "cpu_def.vh"

module de_ex_reg(
  input clk,
  input rst,

  input [3:0] stall,
  input [2:0] flush,

  input                   de_out_valid          ,
  input [           31:0] de_out_pc             ,
  input                   de_out_br_pre_taken   ,
  input [           31:0] de_out_br_pre_pc      ,
  input [           31:0] de_out_rf_rdata_0     ,
  input [           31:0] de_out_rf_rdata_1     ,
  input [           31:0] de_out_hl_rdata       ,
  input [           31:0] de_out_cp0_rdata      ,
  input [            4:0] de_out_rs             ,
  input [            4:0] de_out_rt             ,
  input [            4:0] de_out_rd             ,
  input [            4:0] de_out_sa             ,
  input [           31:0] de_out_simm           ,
  input [           31:0] de_out_uimm           ,
  input [           31:0] de_out_addr           ,
  input [           12:0] de_out_alu_op         ,
  input                   de_out_sel_alu_src_0  ,
  input [            1:0] de_out_sel_alu_src_1  ,
  input [            1:0] de_out_sel_rf_waddr   ,
  input [            1:0] de_out_sel_br_target  ,
  input                   de_out_sel_hl_wdata_ex,
  input                   de_out_read_mem       ,
  input                   de_out_write_mem      ,
  input                   de_out_branch         ,
  input [`NR_LD_OP - 1:0] de_out_ld_op          ,
  input [`NR_ST_OP - 1:0] de_out_st_op          ,
  input [`NR_BR_OP - 1:0] de_out_br_op          ,
  input                   de_out_mul            ,
  input                   de_out_mul_sign       ,
  input                   de_out_div            ,
  input                   de_out_div_sign       ,
  input                   de_out_chk_ov         ,
  input [           31:0] de_out_br_target      ,
  input [           31:0] de_out_jp_target      ,

  input                   de_out_write_rf       ,
  input [            2:0] de_out_sel_rf_wdata   ,
  input [            1:0] de_out_write_hl       ,
  input                   de_out_sel_hl_wdata   ,
  input [            2:0] de_out_cp0_wsel       ,
  input                   de_out_cp0_wen        ,
  input                   de_out_ft_tlbre       ,
  input                   de_out_ft_tlbi        ,
  input                   de_out_ft_adel        ,
  input                   de_out_sys            ,
  input                   de_out_brk            ,
  input                   de_out_ri             ,
  input                   de_out_eret           ,
  input                   de_out_tlbp           ,
  input                   de_out_tlbr           ,
  input                   de_out_tlbwi          ,
  input                   de_out_tlbwr          ,

  output reg                   ex_in_valid          ,
  output reg [           31:0] ex_in_pc             ,
  output reg                   ex_in_br_pre_taken   ,
  output reg [           31:0] ex_in_br_pre_pc      ,
  output reg [           31:0] ex_in_rf_rdata_0     ,
  output reg [           31:0] ex_in_rf_rdata_1     ,
  output reg [           31:0] ex_in_hl_rdata       ,
  output reg [           31:0] ex_in_cp0_rdata      ,
  output reg [            4:0] ex_in_rs             ,
  output reg [            4:0] ex_in_rt             ,
  output reg [            4:0] ex_in_rd             ,
  output reg [            4:0] ex_in_sa             ,
  output reg [           31:0] ex_in_simm           ,
  output reg [           31:0] ex_in_uimm           ,
  output reg [           31:0] ex_in_addr           ,
  output reg [           12:0] ex_in_alu_op         ,
  output reg                   ex_in_sel_alu_src_0  ,
  output reg [            1:0] ex_in_sel_alu_src_1  ,
  output reg [            1:0] ex_in_sel_rf_waddr   ,
  output reg [            1:0] ex_in_sel_br_target  ,
  output reg                   ex_in_sel_hl_wdata_ex,
  output reg                   ex_in_read_mem       ,
  output reg                   ex_in_write_mem      ,
  output reg                   ex_in_branch         ,
  output reg [`NR_LD_OP - 1:0] ex_in_ld_op          ,
  output reg [`NR_ST_OP - 1:0] ex_in_st_op          ,
  output reg [`NR_BR_OP - 1:0] ex_in_br_op          ,
  output reg                   ex_in_mul            ,
  output reg                   ex_in_mul_sign       ,
  output reg                   ex_in_div            ,
  output reg                   ex_in_div_sign       ,
  output reg                   ex_in_chk_ov         ,
  output reg [           31:0] ex_in_br_target      ,
  output reg [           31:0] ex_in_jp_target      ,

  output reg                   ex_in_write_rf       ,
  output reg [            2:0] ex_in_sel_rf_wdata   ,
  output reg [            1:0] ex_in_write_hl       ,
  output reg                   ex_in_sel_hl_wdata   ,
  output reg [            2:0] ex_in_cp0_wsel       ,
  output reg                   ex_in_cp0_wen        ,
  output reg                   ex_in_ft_tlbre       ,
  output reg                   ex_in_ft_tlbi        ,
  output reg                   ex_in_ft_adel        ,
  output reg                   ex_in_sys            ,
  output reg                   ex_in_brk            ,
  output reg                   ex_in_ri             ,
  output reg                   ex_in_eret           ,
  output reg                   ex_in_tlbp           ,
  output reg                   ex_in_tlbr           ,
  output reg                   ex_in_tlbwi          ,
  output reg                   ex_in_tlbwr          
);

  always@(posedge clk) begin
    if (rst || flush[1]) begin
      ex_in_valid <= 1'b0;
    // end else if (stall[1] && !stall[2]) begin
    //   ex_in_valid <= 1'b0;
    end else if (!stall[1]) begin
      ex_in_valid <= de_out_valid;
    end
  end
 
  always@(posedge clk) begin
    if (!stall[1]) begin
      ex_in_pc              <= de_out_pc             ;
      ex_in_br_pre_taken    <= de_out_br_pre_taken   ;
      ex_in_br_pre_pc       <= de_out_br_pre_pc      ;
      ex_in_rf_rdata_0      <= de_out_rf_rdata_0     ;
      ex_in_rf_rdata_1      <= de_out_rf_rdata_1     ;
      ex_in_hl_rdata        <= de_out_hl_rdata       ;
      ex_in_cp0_rdata       <= de_out_cp0_rdata      ;
      ex_in_rs              <= de_out_rs             ;
      ex_in_rt              <= de_out_rt             ;
      ex_in_rd              <= de_out_rd             ;
      ex_in_sa              <= de_out_sa             ;
      ex_in_simm            <= de_out_simm           ;
      ex_in_uimm            <= de_out_uimm           ;
      ex_in_addr            <= de_out_addr           ;
      ex_in_alu_op          <= de_out_alu_op         ;
      ex_in_sel_alu_src_0   <= de_out_sel_alu_src_0  ;
      ex_in_sel_alu_src_1   <= de_out_sel_alu_src_1  ;
      ex_in_sel_rf_waddr    <= de_out_sel_rf_waddr   ;
      ex_in_sel_br_target   <= de_out_sel_br_target  ;
      ex_in_sel_hl_wdata_ex <= de_out_sel_hl_wdata_ex;
      ex_in_read_mem        <= de_out_read_mem       ;
      ex_in_write_mem       <= de_out_write_mem      ;
      ex_in_branch          <= de_out_branch         ;
      ex_in_ld_op           <= de_out_ld_op          ;
      ex_in_st_op           <= de_out_st_op          ;
      ex_in_br_op           <= de_out_br_op          ;
      ex_in_mul             <= de_out_mul            ;
      ex_in_mul_sign        <= de_out_mul_sign       ;
      ex_in_div             <= de_out_div            ;
      ex_in_div_sign        <= de_out_div_sign       ;
      ex_in_chk_ov          <= de_out_chk_ov         ;
      ex_in_br_target       <= de_out_br_target      ;
      ex_in_jp_target       <= de_out_jp_target      ;

      ex_in_write_rf        <= de_out_write_rf       ;
      ex_in_sel_rf_wdata    <= de_out_sel_rf_wdata   ;
      ex_in_write_hl        <= de_out_write_hl       ;
      ex_in_sel_hl_wdata    <= de_out_sel_hl_wdata   ;
      ex_in_cp0_wsel        <= de_out_cp0_wsel       ;
      ex_in_cp0_wen         <= de_out_cp0_wen        ;
      ex_in_ft_tlbre        <= de_out_ft_tlbre       ;
      ex_in_ft_tlbi         <= de_out_ft_tlbi        ; 
      ex_in_ft_adel         <= de_out_ft_adel        ; 
      ex_in_sys             <= de_out_sys            ;
      ex_in_brk             <= de_out_brk            ;
      ex_in_ri              <= de_out_ri             ;
      ex_in_eret            <= de_out_eret           ;
      ex_in_tlbp            <= de_out_tlbp           ;
      ex_in_tlbr            <= de_out_tlbr           ;
      ex_in_tlbwi           <= de_out_tlbwi          ;
      ex_in_tlbwr           <= de_out_tlbwr          ;
    end
  end

endmodule